#include "stock_analyzer.h"
#include <algorithm>
#include <cmath>
#include <map>
#include <iostream>
#include <cstring>

// 为计算kdj数据
struct kdj_data{
    double k;
    double d;
    double j;
    double rsv;
    std::vector<double> k_list;
    std::vector<double> d_list;
    std::vector<double> j_list;
    std::vector<double> rsv_list;
    // 初始化:
    void calculate_kdj_init(const std::vector<StockData>& stockData)
    {
        const int period_setting = 9;
        // 计算rsv:
        {
            for (int i = 0; i < stockData.size(); i++) {
                double minLow = std::numeric_limits<double>::max();
                double maxHigh = std::numeric_limits<double>::lowest();
                for (size_t i_2 = i - period_setting; i_2 < i && i_2>=0; ++i_2) {
                    minLow = std::min(minLow, static_cast<double>(stockData[i_2].low));
                    maxHigh = std::max(maxHigh, static_cast<double>(stockData[i_2].high));
                }
                
                double close = stockData[i].close;    
                if(minLow == std::numeric_limits<double>::max())minLow = close-1;
                if(maxHigh == std::numeric_limits<double>::max())maxHigh = close+1;
                double rsv = (close - minLow) / (maxHigh - minLow) * 100;
                rsv_list.push_back(rsv);
            }
        }
        // 计算kdj:
        {
            double k = 50.0, d = 50.0;
            for (size_t i = 0; i < rsv_list.size(); ++i) {
                // std::cout<<"####    rsv:"<< rsv[i]<<std::endl;
                k = (2.0 / 3.0) * k + (1.0 / 3.0) * rsv_list[i];
                d = (2.0 / 3.0) * d + (1.0 / 3.0) * k;
                double j = 3.0 * k - 2.0 * d;
                k_list.push_back(k);
                d_list.push_back(d);
                j_list.push_back(j);
            }
        }
    }

    size_t getDateIndex_inner(const std::string &date,const std::map<std::string,size_t> &dateRangeMap)
    {
        // 取下标:
        auto it_end = dateRangeMap.lower_bound(date);
        if(dateRangeMap.end()==it_end)return 0;
        if(!dateRangeMap.contains(date))
        {
            --it_end;
        }
        size_t endIndex = it_end->second;
        return endIndex;
    }

    // 是普通叉
    bool is_normal_cross(const std::string &date,const std::map<std::string,size_t> &dateRangeMap)
    {
        size_t endIndex = getDateIndex_inner(date,dateRangeMap);
        if(0==endIndex)return false;// 只有第0天的数据,是没法判断出叉的
        k = k_list[endIndex], d = d_list[endIndex], j = j_list[endIndex];   

        return (k > d && k_list[endIndex-2] < d_list[endIndex-2]);
    }

    // 是金叉
    bool is_golden_cross(const std::string &date,const std::map<std::string,size_t> &dateRangeMap)
    {
        size_t endIndex = getDateIndex_inner(date,dateRangeMap);
        if(0==endIndex)return false;// 只有第0天的数据,是没法判断出叉的
        k = k_list[endIndex], d = d_list[endIndex], j = j_list[endIndex];   
        
        if(k<10&&d<20&&j<0)
        {
            return (k > d && k_list[endIndex-2] < d_list[endIndex-2]);
        }
        return false;
    }

    // 是超卖
    bool is_oversold(const std::string &date,const std::map<std::string,size_t> &dateRangeMap)
    {
        size_t endIndex = getDateIndex_inner(date,dateRangeMap);
        if(0==endIndex)return false;// 只有第0天的数据,是没法判断出叉的
        k = k_list[endIndex], d = d_list[endIndex], j = j_list[endIndex];   
        
        return (k<10&&d<20&&j<0);
    }

    // 是超卖后的第一个普通叉
    bool isAfterOversold(const std::string &date,const std::map<std::string,size_t> &dateRangeMap)
    {
        size_t endIndex = getDateIndex_inner(date,dateRangeMap);
        if(0==endIndex)return false;// 只有第0天的数据,是没法判断出叉的
        k = k_list[endIndex], d = d_list[endIndex], j = j_list[endIndex];   
        
        // 在现在是普通叉的情况下
        if((k > d && k_list[endIndex-2] < d_list[endIndex-2]))
        {
            for(size_t i=endIndex-2;i>=0&&i>endIndex-10;i--)
            {
                // 在另一个叉退出循环, 不管是什么叉
                if(
                    k_list[i] > d_list[i] && k_list[i-2] < d_list[i-2]
                    ||
                    k_list[i] < d_list[i] && k_list[i-2] > d_list[i-2]
                )
                {
                    return false;
                }
                // 判断是超卖:
                if((k_list[i]<10&&d_list[i]<20&&j_list[i]<0))
                {
                    return true;
                }
            }
        }        
        return false;
    }

    // 是超买
    bool isOverbought(const std::string &date,const std::map<std::string,size_t> &dateRangeMap)
    {
        size_t endIndex = getDateIndex_inner(date,dateRangeMap);
        if(0==endIndex)return false;// 只有第0天的数据,是没法判断出叉的
        k = k_list[endIndex], d = d_list[endIndex], j = j_list[endIndex];
        return (k>90&&d>80&&j>100);
    }
};

// 背离数据
struct macd_depart{
    // std::vector<double> macd_valleys;// 最近的各个谷
    // std::vector<double> macd_valleys_price;// 谷对应的价格
    std::vector<double> macd_depart_value;// 背离值
    std::vector<double> macd_level;// 用于计算macd新谷底
};

struct inner_data{
    kdj_data kdj;
    // 日期对应的下标
    std::map<std::string,size_t> dateRangeMap;
    std::vector<double> arr_macd_ma30_level;
    std::vector<double> arr_price_ma30_level;
    std::vector<double> arr_macd_depart;// 背离值
    std::vector<double> arr_macd_depart_consecutive_days;// 背离值
    std::vector<double> arr_macd_depart_consecutive_days_of_gains;// 背离值连续上涨天数
    std::vector<double> arr_macd_depart_speed_up_days;// 背离值上涨速度突然加大的天数
    std::vector<double> arr_macd_change_rate;// macd涨跌幅度
    std::vector<double> arr_macd_activity_rate_90_day;// macd的活跃度 90天内前45天与后45天的比值
    std::vector<double> arr_ma120;// 120日均线
    std::vector<double> arr_are_between_price_ma120_day; // 价格与120线之间的"面积"
    std::map<std::string,double> arr_are_between_price_ma120_week;// 价格与120线之间的"面积"

    // 初始化下标列表:
    void init_date_range_map(const std::vector<StockData>& stockData)
    {
        for(size_t i=0;i<stockData.size();i++)
        {
            dateRangeMap[stockData[i].trade_date] = i;
        }
    }
    // 拷贝日期字串
    char copyed_date[255];

    void copy_date_from_cursor(const char* cursor)
    {
        std::strncpy(copyed_date,cursor,255);
        // 确保字符串以 null 结尾
        copyed_date[sizeof(copyed_date) - 1] = '\0';
    }

    // 计算指数移动平均线 (EMA)
    std::vector<double> calculateEMA(const std::vector<double> &prices,int period) {
        if(prices.size()<=period)abort();
        std::vector<double> ema(prices.size(), 0.0);
        double multiplier = 2.0 / (period + 1);
        ema[period - 1] = 0.0;
        for (int i = 0; i < period; ++i) {
            ema[period - 1] += prices[i];
        }
        ema[period - 1] /= period;

        for (int i = period; i < prices.size(); ++i) {
            ema[i] = (prices[i] - ema[i - 1]) * multiplier + ema[i - 1];
        }
        return ema;
    }

    // 计算MACD
    void calculateMACD(std::vector<StockData>& MACDData,int shortPeriod = 6, int longPeriod = 13, int signalPeriod = 5) {
        if(MACDData.size()<=longPeriod)
        {
            std::cout<<"太短 没法算MACD"<<std::endl;
            return;
        }
        std::vector<double> prices(MACDData.size(), 0.0) ;
        for (int i = 0; i < MACDData.size(); ++i) {
            prices[i] = MACDData[i].close;
        }
        std::vector<double> shortEMA = calculateEMA(prices,shortPeriod);
        std::vector<double> longEMA = calculateEMA(prices,longPeriod);
        std::vector<double> macdLine(prices.size(), 0.0);
        std::vector<double> signalLine(prices.size(), 0.0);
        std::vector<double> histogram(prices.size(), 0.0);

        for (int i = longPeriod - 1; i < prices.size(); ++i) {
            macdLine[i] = shortEMA[i] - longEMA[i];
        }

        signalLine = calculateEMA(macdLine, signalPeriod);

        for (int i = longPeriod + signalPeriod - 2; i < prices.size(); ++i) {
            histogram[i] = macdLine[i] - signalLine[i];
        }

        for(int i=0;i<MACDData.size();i++)
        {
            MACDData[i].macd = macdLine[i];
            MACDData[i].macd_signal = signalLine[i];
            MACDData[i].macd_histogram = histogram[i];
        }

        //return histogram;
    }

    // MACD分析函数
    // 算出价格水平与MACD水平 用于背离值的计算
    void calculatePriceMa30LevelAndMacdMa30Level(std::vector<StockData>& MACDData)
    {
        arr_macd_ma30_level = std::vector<double>(MACDData.size(),0);
        arr_price_ma30_level = std::vector<double>(MACDData.size(),0);
        arr_macd_change_rate = std::vector<double>(arr_macd_ma30_level.size(),0);
        arr_macd_activity_rate_90_day = std::vector<double>(arr_macd_ma30_level.size(),0);
        for(size_t i=120;i<MACDData.size();i++)
        {
            double price_120_max = -9e9;
            double price_120_min = 9e9;            
            // 算出120天的最大值最小值:
            for(size_t j=i;j>0&&j>i-120;--j)
            {
                if(MACDData[j].close>price_120_max)
                {
                    price_120_max = MACDData[j].close;
                }
                else if(MACDData[j].close<price_120_min)
                {
                    price_120_min = MACDData[j].close;
                }
            }// END 算出120天的最大值最小值

            // 算出30天内的均价
            double total_price = 0;
            for(size_t j=i;j>0&&j>i-30;--j)
            {
                total_price+=MACDData[j].close;
            }
            double avg_price = total_price/30;

            // 均价水平:
            arr_price_ma30_level[i]=(avg_price-price_120_min)/(price_120_max-price_120_min);

            double macd_120_max = -9e9;
            double macd_120_min = 9e9;
            for(size_t j=i;j>0&&j>i-120;--j)
            {
                if(MACDData[j].macd>macd_120_max)
                {
                    macd_120_max = MACDData[j].macd;
                }
                else if(MACDData[j].macd<macd_120_min)
                {
                    macd_120_min = MACDData[j].macd;
                }
            }
            // 算出30天内的平均macd
            double total_macd = 0;
            for(size_t j=i;j>0&&j>i-30;--j)
            {
                total_macd+=MACDData[j].macd;
            }
            double avg_macd = total_macd/30;
            arr_macd_ma30_level[i]=(avg_macd-macd_120_min)/(macd_120_max-macd_120_min);       
            arr_macd_change_rate[i] = abs( MACDData[i].macd - MACDData[i-1].macd);  
        }

        // 计算出每天的背离值:
        arr_macd_depart = std::vector<double>(arr_macd_ma30_level.size(),0);
        arr_macd_depart_consecutive_days = std::vector<double>(arr_macd_ma30_level.size(),0);
        arr_macd_depart_consecutive_days_of_gains = std::vector<double>(arr_macd_ma30_level.size(),0);
        arr_macd_depart_speed_up_days = std::vector<double>(arr_macd_ma30_level.size(),0);
        size_t depart_consecutive=0;// 连续背离
        size_t depart_consecutive_of_gains=0;// 连续背离上涨
        size_t depart_speed_up_days=0;// 背离连续增速
        for(size_t i=120;i<arr_macd_ma30_level.size();i++)
        {
            arr_macd_depart[i] = arr_macd_ma30_level[i]-arr_price_ma30_level[i];
            if(arr_macd_depart[i]>0)
            {
                ++depart_consecutive;
            }
            else
            {
                depart_consecutive=0;
            }
            arr_macd_depart_consecutive_days[i]=depart_consecutive;
            if(arr_macd_depart[i]>arr_macd_depart[i-1])
            {
                ++depart_consecutive_of_gains;
            }
            else
            {
                depart_consecutive_of_gains=0;
            }
            arr_macd_depart_consecutive_days_of_gains[i] = depart_consecutive_of_gains;
            // 上涨速度连续加快:
            double speed_old = arr_macd_ma30_level[i-1]-arr_macd_ma30_level[i-2];
            double speed_now = arr_macd_ma30_level[i]-arr_macd_ma30_level[i-1];
            if(speed_now/speed_old>1.25)
            {
                ++depart_speed_up_days;
            }
            else
            {
                depart_speed_up_days=0;

            }
            // macd值在下降中才是新底, 否则保持初始值0不变
            if(MACDData[i].macd<MACDData[i-1].macd)
            {
                arr_macd_depart_speed_up_days[i] = depart_speed_up_days;
            }
        }// END for(size_t i=120;i<arr_macd_ma30_level.size();i++)
    
        // arr_macd_change_rate => arr_macd_activity_rate_90_day
        // 90天内的活跃度变化:
        for(size_t i=91;i<arr_macd_activity_rate_90_day.size();i++)
        {
            size_t index_2 = i;            
            // 近45天总量
            double total_macd_change_rate_close_part = 0;
            for(;index_2>0&&index_2>i-45;--index_2)
            {
                total_macd_change_rate_close_part+=arr_macd_change_rate[index_2];
            }
            // 远45天总量
            double total_macd_change_rate_far_part = 0;
            for(;index_2>0&&index_2>i-90;--index_2)
            {
                total_macd_change_rate_far_part+=arr_macd_change_rate[index_2];
            }
            // std::cout<<"#360  total_macd_change_rate_close_part:"<< total_macd_change_rate_close_part <<","<< total_macd_change_rate_far_part <<std::endl;
            arr_macd_activity_rate_90_day[i] = total_macd_change_rate_close_part/total_macd_change_rate_far_part;
        }// END for(size_t i=91;i<arr_macd_activity_rate_90_day.size();i++)
    }// END calculatePriceMa30LevelAndMacdMa30Level

    // 计算 新低且底背离
    // 背离的两个条件: 1. 新底比旧底高, 2. 在新底时的股价比旧底低
    // 背离的意义在于: 越来越不想跌了
    // 需要纠正一个错误,如果已经是大涨过后, 那么这个底背离已经过时了
    bool is_new_lows_and_bottoms_diverge(const std::string &date,std::vector<StockData>& MACDData)
    {

        return false;


        // // 用多长的时间去判断
        // const size_t new_low_date_range = 60;
        // // 当前日期的下标:
        // size_t endIndex = kdj.getDateIndex_inner(date,dateRangeMap);
        // float end_macd = MACDData[endIndex].macd;
        // bool first_time=true, go_down=false, go_up = false;
        // float last_macd = 0;
        // std::vector<float> macd_top_list;// 顶数组
        // std::vector<float> macd_bottom_list;// 底数组
        // std::vector<float> macd_bottom_list_price;// 底数组对应的价格
        // float last_height = 0;// 最高峰
        // for(size_t i=endIndex;i>=0&&i>endIndex-new_low_date_range;i--)
        // {
        //     float current_macd = MACDData[i].macd;
        //     if(first_time)
        //     {
        //         first_time = false;
        //         if(current_macd<end_macd)
        //         {
        //             go_down = true;
        //         }
        //         else
        //         {
        //             go_up = true;
        //         }
        //     }// END if(first_time)
        //     else
        //     {
        //         if(go_up)
        //         {
        //             if(current_macd<last_macd)
        //             {
        //                 go_up = false;
        //                 go_down = true;
        //                 if(0<last_macd)
        //                 {
        //                     // 新高
        //                     macd_top_list.push_back(last_macd);
        //                     if(0!=last_height && 1==macd_bottom_list.size())
        //                     {
        //                         if(last_macd > abs(macd_bottom_list[0]))
        //                         {
        //                             return false;// 刚刚大涨过
        //                         }
        //                     }
        //                 }
        //             }
        //         }
        //         else if(go_down)
        //         {
        //             if(current_macd>last_macd)
        //             {
        //                 go_down = false;
        //                 go_up = true;
        //                 if(current_macd<0)
        //                 {
        //                     // 零轴下的新低
        //                     macd_bottom_list.push_back(last_macd);
        //                     macd_bottom_list_price.push_back(MACDData[i].close);
        //                 }
        //             }
        //         }
        //     }
            
        //     last_macd = current_macd;
        // }// END for

        // // 判断是已经大涨过后了.
        // if(macd_top_list.size()!=0 && macd_bottom_list.size()!=0)
        // {
        //     if(macd_top_list[0]>abs(macd_bottom_list[0]))
        //     {
        //         return false;
        //     }
        // }

        // // 最后下判断
        // bool keep_going_up = true;
        // if(macd_bottom_list.size()>1)
        // {
        //     for(size_t i=0;i<2;i++) // 判断就近两个谷底就好
        //     {
        //         // 越跌越凶的情况
        //         if(macd_bottom_list[i]>macd_bottom_list[i+1])
        //         {
        //             return false;
        //         }
        //         // 不判断这段, 是因为有时会先涨一点, 后面涨多点, 背离后会一个小波动, 大涨在后面, 有这段就吃不到后面的大涨.
        //         // else if(macd_bottom_list_price[i]>macd_bottom_list_price[i+1])
        //         // {
        //         //     // 不是背离的情况
        //         //     return false;
        //         // }
        //     }
        //     return true;
        // }
        // else
        // {
        //     return false;
        // }
    }

    // // 计算背离数据
    // macd_depart calculate_macd_depart_from(const std::string& date,std::vector<StockData>& MACDData)
    // {
    //     // 算出macd的各个谷及其对应的时间点(这里时间点即下标点)
    //     const size_t perdio = 365;
    //     size_t endIndex = kdj.getDateIndex_inner(date,dateRangeMap);
    //     if(endIndex<=perdio)return {};
    //     bool is_under_water = false;
    //     float min_of_this_valley = 9e9;
    //     size_t index_of_deep_valley = 0;
    //     std::vector<double> macd_valleys;  
    //     std::vector<double> macd_valleys_price;
    //     for(size_t i=endIndex;i>=0&&i>endIndex-perdio;i--)
    //     {
    //         // if(MACDData[i].macd<0)
    //         // {
    //         //     if(!is_under_water)
    //         //     {
    //         //         // 进入一个谷
    //         //         is_under_water = true;
    //         //     }
                
    //         //     if(min_of_this_valley > MACDData[i].macd)
    //         //     {
    //         //         min_of_this_valley = MACDData[i].macd;
    //         //         index_of_deep_valley = i;
    //         //     }
    //         // }
    //         // else if(is_under_water&&MACDData[i].macd>0)
    //         // {
    //         //     // 出谷
    //         //     is_under_water = false;
    //         //     macd_valleys.push_back(min_of_this_valley);
    //         //     macd_valleys_price.push_back(MACDData[i].close);
    //         //     min_of_this_valley = 9e9;// 复初始值
    //         // }
    //         macd_valleys.push_back(MACDData[i].macd);
    //         macd_valleys_price.push_back(MACDData[i].close);
    //     }
    //     macd_depart result_data;
    //     result_data.macd_valleys = macd_valleys;
    //     result_data.macd_valleys_price = macd_valleys_price;
    //     return result_data;
    // }


    float arrange_value(const std::string& date,std::vector<StockData>& MACDData)
    {
        const size_t range = 30;// 时间范围
        size_t endIndex = kdj.getDateIndex_inner(date,dateRangeMap);

        float max_macd = -9e9;
        float min_macd = 9e9;
        for(size_t i=endIndex;i>=0&&i>endIndex-range;i--)
        {
            if(MACDData[i].macd>max_macd)
            {
                max_macd = MACDData[i].macd;
            }
            if(MACDData[i].macd<min_macd)
            {
                min_macd = MACDData[i].macd;
            }
        }
        float middle = (max_macd+min_macd)/2;

        // // 加点料:
        // bool is_in_cave = false;
        // float min_macd_2 = 9e9;
        // for(size_t i=endIndex;i>=0&&i>endIndex-range;i--)
        // {
        //     if(MACDData[i].macd<0)is_in_cave=true;
        //     if(is_in_cave==true && MACDData[i].macd>0)break;// 出谷
        //     if(is_in_cave)
        //     {
        //         if(min_macd_2>MACDData[i].macd)
        //         {
        //             min_macd_2 = MACDData[i].macd;
        //         }
        //     }
        // }
        //  - min_macd_2

        return max_macd-middle;
        // 正值: 赌徒的赢率: 0.387387  平均胜率:0.338893
        // 负值: 赌徒的赢率: 0.195312

        // float macd_total = 0;
        // for(size_t i=endIndex;i>=0&&i>endIndex-range;i--)
        // {
        //     macd_total+=MACDData[i].macd;
        // }
        // return -macd_total/range;
    }
    
    double calculateMA(size_t index, int period,std::vector<StockData>& _stockData)
    {
        //int index = getDateIndex(date);
        if (index < period-1) return 0.0;  // 数据不足20天
    
        double sum = 0.0;
        for (int i = 0; i < period; ++i) {
            sum += _stockData[index - i].close;
        }
        return sum / period;
    }
    

    // 面积:
    void calculatePriceArea(std::vector<StockData>& StockDatas)
    {
        arr_are_between_price_ma120_day = std::vector<double>(StockDatas.size(),0);
        arr_ma120 = std::vector<double>(StockDatas.size(),0);
        //arr_are_between_price_ma120_week = std::map<std::string,double>();// 这个就让它动态分配吧

        for(size_t i=0;i<StockDatas.size();i++)
        {
            //计算ma120
            arr_ma120[i] = calculateMA(i,120,StockDatas);
            arr_are_between_price_ma120_day[i] = arr_ma120[i] - StockDatas[i].close;
        }

        // 在计算周数据时,以最后一天为起点, 因为程序的目的是为了做预判, 需要算到最后一天, 如果最后几天不足一星期, 就不准.
        for(int i=StockDatas.size()-1;i>=0&&i>6;i-=7)
        {
            double total_price = 0;
            for(int j=0;j<7;++j)
            {
                int index_3 = i-j;
                total_price += arr_are_between_price_ma120_day[index_3];
            }// END for
            arr_are_between_price_ma120_week[StockDatas[i-6].trade_date] = total_price;
        }// END for
    }

    // 取N天的Ma120数据
    // 倒序排列
    std::vector<std::pair<std::string,double>> getMa120Area(std::string date,size_t n)
    {
        std::vector<std::pair<std::string,double>> result_list = std::vector<std::pair<std::string,double>>(n);
        // BEGIN 防范
        if(n>arr_are_between_price_ma120_week.size())
        {
            return result_list;
        }
        // END 防范
        // 找下标:
        auto found = arr_are_between_price_ma120_week.lower_bound(date);
        if(arr_are_between_price_ma120_week.end()==found)
        {
            auto rBegin = arr_are_between_price_ma120_week.rbegin();
            for(size_t i=0;i<n;++i)
            {
                result_list[i] = std::make_pair(rBegin->first,rBegin->second);
                ++rBegin;
                if(arr_are_between_price_ma120_week.rend()==rBegin)break;
            }
        }
        else
        {
            for(size_t i=0;i<n;++i)
            {
                -- found;
                if(arr_are_between_price_ma120_week.end()==found)break;
                result_list[i] = std::make_pair(found->first,found->second);
            }
        }
        return result_list;
    }
};

#define inner() (reinterpret_cast<inner_data*>(m_innerData))



// 构造函数
StockAnalyzer::StockAnalyzer(const std::vector<StockData>& stockData) 
    : m_stockData(stockData) {
    m_innerData = (size_t) new inner_data;
    // 初始化KDJ
    inner()->kdj.calculate_kdj_init(stockData);
    inner()->init_date_range_map(stockData);
    inner()->calculateMACD(m_stockData);
    inner()->calculatePriceMa30LevelAndMacdMa30Level(m_stockData);
    inner()->calculatePriceArea(m_stockData);
}

// 获取指定日期在数据中的索引
int StockAnalyzer::getDateIndex(const std::string& date) {
    // if(date.empty())std::cout<<"\t#131 空"<<std::endl;// 无法判断为空, 那是个野指针
    // std::cout<< "\tgetDateIndex BEGIN"<<"\tdate指针:"<< (size_t)date.c_str() <<"\tdate:"<<date <<"\trangeMap:"<< inner()->dateRangeMap.size() <<std::endl;
    auto it_end = inner()->dateRangeMap.lower_bound(date);

    if(inner()->dateRangeMap.end()==it_end)
    {
        // std::cout<<"\tgetDateIndex END3  没查到数据"<<"\tdate:"<< date<<std::endl;
        return 0;
    }
    // std::cout<< "\tgetDateIndex #123 index:"<< it_end->second <<"\tdate:"<< date<<std::endl;
    if(inner()->dateRangeMap.begin() == it_end)
    {
        // std::cout<<"\tgetDateIndex END4  怕是有些股票还没上市, 还没到开始的时候."<<"\tdate:"<< date<<std::endl;
        return it_end->second;// 怕是有些股票还没上市, 还没到开始的时候.
    }
    if(!inner()->dateRangeMap.contains(date))
    {
        --it_end;
    }
    if(inner()->dateRangeMap.end()==it_end)
    {
        // std::cout<< "\tgetDateIndex END2 return 0;" <<"\tdate:"<< date<<std::endl;
        return 0;
    }
    size_t endIndex = it_end->second;
    // std::cout<< "\tgetDateIndex END  endIndex:"<< endIndex <<"\tdateRangeMap.size():"<< inner()->dateRangeMap.size() <<"\tdate:"<< date<<std::endl;
    return endIndex; 
}

// 计算K线实体大小
double StockAnalyzer::calculateBodySize(const StockData& data) {
    return std::abs(data.close - data.open);
}

// 计算K线上影线长度
double StockAnalyzer::calculateUpperShadow(const StockData& data) {
    return data.high - std::max(data.open, data.close);
}

// 计算K线下影线长度
double StockAnalyzer::calculateLowerShadow(const StockData& data) {
    return std::min(data.open, data.close) - data.low;
}

// 判断是否星线
bool StockAnalyzer::isStarPattern(const StockData& current) {
    double bodySize = calculateBodySize(current);
    double upperShadow = calculateUpperShadow(current);
    double lowerShadow = calculateLowerShadow(current);
    
    // 星线特征：
    // 1. 实体较小（小于上下影线）
    // 2. 上下影线较长
    // 3. 实体与影线比例大于3
    return bodySize < std::min(upperShadow, lowerShadow) &&
           (upperShadow + lowerShadow) / bodySize > 3.0;
}

// 判断是否锤子线
bool StockAnalyzer::isHammerPattern(const StockData& current) {
    double bodySize = calculateBodySize(current);
    double upperShadow = calculateUpperShadow(current);
    double lowerShadow = calculateLowerShadow(current);
    
    // 锤子线特征：
    // 1. 下影线较长（至少是实体的2倍）
    // 2. 上影线较短
    // 3. 实体较小
    return lowerShadow > bodySize * 2.0 &&
           upperShadow < bodySize &&
           bodySize < (current.high - current.low) * 0.3;
}

// 判断是否放量洗盘
bool StockAnalyzer::isVolumeWash(const StockData& current, double ma60Volume) {
    return current.vol > ma60Volume * 2 ;
}

// 判断是否放量卖出
bool StockAnalyzer::isVolumeSell(const StockData& current, double ma60Volume) {
    return current.vol > ma60Volume * 1.5 ;
}

float StockAnalyzer::calculateVolumeMA(int period, const std::string& date)
{
    int index = getDateIndex(date);
    if (index < period-1) return 0.0;  // 数据不足period天
    
    double sum = 0.0;
    for (int i = 0; i < period; ++i) {
        sum += m_stockData[index - i].vol;
    }
    return sum / period;
}

// 分析指定日期的数据
stock_analyzer_data StockAnalyzer::analyzeDate() {
    const std::string _date = inner()->copyed_date;
    // std::cout<<"StockAnalyzer::analyzeDate() 开始"<<std::endl;
    stock_analyzer_data result = {};
    int index = getDateIndex(_date);
    if (index < 1) return result;// 必须有前后两天能够计算某些指标
    // // std::cout<<"\t#370"<<std::endl;
    const StockData& current = m_stockData[index];
    const StockData& lastDay = m_stockData[index-1];
    // // std::cout<<"#272 [index-1]"<< index-1 <<"\tlastDay.trade_date.size():"<< lastDay.trade_date.size() <<std::endl;
    // std::cout << "\t243 date:"<<_date<< std::endl;
    result.currentPrice = current.close;
    result.lastDayPrice = lastDay.close;
    result.openPrice = current.open;
    // 设置均线数据
    result.ma5 = calculateMA(5,_date); //ma5Volume;
    result.ma10 = calculateMA(10,_date); //ma10Volume;
    result.ma20 = calculateMA(20,_date); //ma20Volume;
    result.ma120 = inner()->arr_ma120[index];// calculateMA(120,_date); //ma20Volume;
    // std::cout << "\t249 date:"<<_date<< std::endl;
    result.lastMa5 = calculateMA(5,lastDay.trade_date);
    // std::cout << "\t251"<< std::endl;
    result.lastMa10 = calculateMA(10,lastDay.trade_date);
    // std::cout << "\t253 date:"<<_date<< std::endl;
    result.lastMa20 = calculateMA(20,lastDay.trade_date);
    result.macd = current.macd;
    result.macd_signal = current.macd_signal;
    result.macd_histogram = current.macd_histogram;
    result.lastMacd_signal = lastDay.macd_signal;
    result.lastMacd = lastDay.macd;
    result.kdj_j = inner()->kdj.j_list[index];
    result.kdj_last_j = inner()->kdj.j_list[index-1];
    // std::cout << "\t254 date:"<<_date<< std::endl;
    // 判断各种形态
    // bool isVolumeWashout = isVolumeWash(current, ma5Volume, ma10Volume);
    bool isStarPat = isStarPattern(current);
    bool isHammerPat = isHammerPattern(current);
    // std::cout << "\t259 date:"<<_date<< std::endl;
    // 设置K线形态标志
    result.isHammerOrStar = isStarPat || isHammerPat;
    // 成交量的关键指标
    result.vol = current.vol;
    result.lastVol = lastDay.vol;
    result.volMa60 = calculateVolumeMA(60,std::string(_date));
    result.isLargeVolumeWashout = isVolumeWash(current,result.volMa60);
    result.isLargeVolumeSellout = isVolumeSell(current,result.volMa60);
    // std::cout << "\t265 date:"<<_date<< std::endl;
    // KDJ基础数据:普通叉金叉:
    result.isKDJCross = inner()->kdj.is_normal_cross(_date,inner()->dateRangeMap);
    result.isKDJGoldenCross = inner()->kdj.is_golden_cross(_date,inner()->dateRangeMap);
    result.isOversold = inner()->kdj.is_oversold(_date,inner()->dateRangeMap);
    result.isAfterOversold = inner()->kdj.isAfterOversold(_date,inner()->dateRangeMap);
    result.isOverbought = inner()->kdj.isOverbought(_date,inner()->dateRangeMap);
    result.isMACDPositive = current.macd>0 && current.macd>current.macd_signal;
    // std::cout<<"result.isMACDGoUp?  "<<  current.macd<<">"<<lastDay.macd<<std::endl;
    result.isMACDGoUp = current.macd>=lastDay.macd; // 为了不在没数据的情况下误判, '>' 改成 '>='
    result.new_lows_and_bottoms_diverge = inner()->is_new_lows_and_bottoms_diverge(std::string(_date),m_stockData);
    // macd_depart _depart = inner()->calculate_macd_depart_from(_date,m_stockData);
    // result.macd_valleys = _depart.macd_valleys;
    // result.macd_valleys_price = _depart.macd_valleys_price;
    result.arrange_value = inner()->arrange_value(_date,m_stockData);
    // 背离:
    result.macd_ma30_level = inner()->arr_macd_ma30_level[index];
    result.price_ma30_level = inner()->arr_price_ma30_level[index];
    result.macd_depart = inner()->arr_macd_depart[index];
    result.macd_depart_consecutive_days = inner()->arr_macd_depart_consecutive_days[index];
    result.macd_depart_consecutive_days_of_gains = inner()->arr_macd_depart_consecutive_days_of_gains[index];
    result.macd_depart_speed_up_days = inner()->arr_macd_depart_speed_up_days[index];
    // 一周周背离有波动的情况:
    for(size_t i=1;i<=7;++i)
    {
        double speed_value = inner()->arr_macd_depart_speed_up_days[index-i];
        if(0<speed_value)
        {
            result.has_depart_speed_up=true;
            break;
        }
    }
    result.macd_activity_rate = inner()->arr_macd_activity_rate_90_day[index];
    result.ma120Area = inner()->getMa120Area(_date,3);


    return result;
}

// 计算均价
double StockAnalyzer::calculateMA(int period, const std::string& date)
{
    int index = getDateIndex(date);
    if (index < period-1) return 0.0;  // 数据不足20天

    double sum = 0.0;
    for (int i = 0; i < period; ++i) {
        sum += m_stockData[index - i].close;
    }
    return sum / period;
}


// 转存日期, 以解决因日期字串的指针失效从而引发的崩溃问题
void StockAnalyzer::copyDateString (const char* date)
{
    inner()->copy_date_from_cursor(date);
}

// 取回股票数据:
std::vector<StockData> &StockAnalyzer::getStockData()
{
    return m_stockData;
}


STOCK_ANALYZER_API StockAnalyzer* createStockAnalyzer(const StockData* data, int dataCount) {
    if (!data || dataCount <= 0) return nullptr;
    std::vector<StockData> stockData(data, data + dataCount);
    return new StockAnalyzer(stockData);
}

STOCK_ANALYZER_API void destroyStockAnalyzer(StockAnalyzer* analyzer) {
    if (analyzer) {
        delete analyzer;
    }
}

STOCK_ANALYZER_API stock_analyzer_data analyzeStockData(StockAnalyzer* analyzer, const char* date) {
    if (!analyzer || !date) {
        return stock_analyzer_data();
    }
    // std::cout<<"analyzeStockData\t字串地址date:"<<(size_t)date<<std::endl;
    // 这里转存没用, 下个崩溃点照样会崩溃.(最终,找到的原因是为取前一天的数据,数组下标为-1因而后面读取的日期是个野指针)
    analyzer->copyDateString(date);
    return analyzer->analyzeDate();
}